#include "StdAfx.h"
#include "./otlkcon_debug.h"

#include <strsafe.h>

otlkcon_debug debugObj;

otlkcon_debug::otlkcon_debug(void)
{
	m_bInitialized = false;
	m_lpAllocateBuffer = NULL;
	m_lpFreeBuffer = NULL;
}

otlkcon_debug::~otlkcon_debug(void)
{
}

void otlkcon_debug::Initialize(LPALLOCATEBUFFER lpAllocateBuffer, LPFREEBUFFER lpFreeBuffer)
{
	if(!m_bInitialized) 
	{
		m_Prop2Str.init(lpAllocateBuffer, lpFreeBuffer);
		m_lpAllocateBuffer = lpAllocateBuffer;
		m_lpFreeBuffer = lpFreeBuffer;
		m_bInitialized = true;
	} // if
}

bool otlkcon_debug::CanTrace(unsigned long ulTraceFlags)
{
	return true;
}

// obtains symbolic prop name if found
void otlkcon_debug::TracePropTag(ULONG ulTraceFlags, ULONG ulPropTag, wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;

	wchar_t szTag[MAX_PATH+1] = {0};
	if(GetTagName(ulPropTag, szTag, cch(szTag)))
	{
		OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: %s\n", lpszMessage, szTag);
	} // if
}

BOOL otlkcon_debug::GetTagName(ULONG ulPropTag, wchar_t* lpszBuffer, size_t cchBufferLenght)
{
	BOOL bResult = FALSE;
	bResult = m_Prop2Str.get(ulPropTag, lpszBuffer, cchBufferLenght);
	return bResult;
}

void otlkcon_debug::TracePropTagArray(
	ULONG ulTraceFlags,
	LPSPropTagArray lpsptaProps,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;
	
	TracePropTagArray(ulTraceFlags, lpsptaProps->aulPropTag, lpsptaProps->cValues, lpszMessage);
}

void otlkcon_debug::TracePropTagArray(
	ULONG ulTraceFlags,
	ULONG *lpPropTags,
	ULONG cValues,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;
	
	OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: cValues = %d\n", lpszMessage, cValues);
	wchar_t szTag[MAX_PATH+1] = {0};
	for(ULONG iProp = 0; iProp < cValues; iProp++)
	{
		if(GetTagName(lpPropTags[iProp], szTag, cch(szTag)))
		{
			OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"\t%s\n", szTag);
		} // if
		else
		{
			OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"\tnone\n", szTag);
		} // else
	} // for
}

void otlkcon_debug::TracePropTagArray(
	ULONG ulTraceFlags,
	LPSPropValue lpProps,
	ULONG cValues,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;
	
	OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: cValues = %d\n", lpszMessage, cValues);
	wchar_t szTag[MAX_PATH+1] = {0};
	for(ULONG iProp = 0; iProp < cValues; iProp++)
	{
		if(GetTagName(lpProps[iProp].ulPropTag, szTag, cch(szTag)))
		{
			OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"\t%s\n", szTag);
		} // if
		else
		{
			OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"\tnone\n", szTag);
		} // else
	} // for
}

void SystemTimeToSTR(
	SYSTEMTIME *pst,
	wchar_t* lpszBuffer,
	size_t cchBufferLenght)
{
	StringCchPrintfW(lpszBuffer, cchBufferLenght,
		L"%02d:%02d:%02d  %02d.%02d.%04d",
		pst->wHour, 
		pst->wMinute, 
		pst->wSecond, 
		pst->wDay, 
		pst->wMonth, 
		pst->wYear);
}

void FileTimeToSTR(
	FILETIME *pft,
	wchar_t* lpszBuffer,
	size_t cchBufferLenght)
{
	SYSTEMTIME st = {0};
	FileTimeToSystemTime( pft , &st);
	SystemTimeToSTR( &st,  lpszBuffer, cchBufferLenght);
}

LPCWSTR GetErrorString(ULONG ulError)
{
	LPCWSTR szErr = L"";

	switch(ulError)
	{        
	case S_FALSE							: szErr = L"S_FALSE";                        break;
	case E_FAIL                             : szErr = L"E_FAIL";                         break;
	case E_INVALIDARG                       : szErr = L"E_INVALIDARG";                   break;
	case E_NOINTERFACE                      : szErr = L"E_NOINTERFACE";                  break;
	case E_OUTOFMEMORY                      : szErr = L"E_OUTOFMEMORY";                  break;
	case E_ACCESSDENIED                     : szErr = L"E_ACCESSDENIED";                 break;

	case MAPI_E_NO_SUPPORT                  : szErr = L"MAPI_E_NO_SUPPORT";              break;
	case MAPI_E_BAD_CHARWIDTH               : szErr = L"MAPI_E_BAD_CHARWIDTH";           break;
	case MAPI_E_STRING_TOO_LONG             : szErr = L"MAPI_E_STRING_TOO_LONG";         break;
	case MAPI_E_UNKNOWN_FLAGS               : szErr = L"MAPI_E_UNKNOWN_FLAGS";           break;
	case MAPI_E_INVALID_ENTRYID             : szErr = L"MAPI_E_INVALID_ENTRYID";         break;
	case MAPI_E_INVALID_OBJECT              : szErr = L"MAPI_E_INVALID_OBJECT";          break;
	case MAPI_E_OBJECT_CHANGED              : szErr = L"MAPI_E_OBJECT_CHANGED";          break;
	case MAPI_E_OBJECT_DELETED              : szErr = L"MAPI_E_OBJECT_DELETED";          break;
	case MAPI_E_BUSY                        : szErr = L"MAPI_E_BUSY";                    break;
	case MAPI_E_NOT_ENOUGH_DISK             : szErr = L"MAPI_E_NOT_ENOUGH_DISK";         break;
	case MAPI_E_NOT_ENOUGH_RESOURCES        : szErr = L"MAPI_E_NOT_ENOUGH_RESOURCES";    break;
	case MAPI_E_NOT_FOUND                   : szErr = L"MAPI_E_NOT_FOUND";               break;
	case MAPI_E_VERSION                     : szErr = L"MAPI_E_VERSION";                 break;
	case MAPI_E_LOGON_FAILED                : szErr = L"MAPI_E_LOGON_FAILED";            break;
	case MAPI_E_SESSION_LIMIT               : szErr = L"MAPI_E_SESSION_LIMIT";           break;
	case MAPI_E_USER_CANCEL                 : szErr = L"MAPI_E_USER_CANCEL";             break;
	case MAPI_E_UNABLE_TO_ABORT             : szErr = L"MAPI_E_UNABLE_TO_ABORT";         break;
	case MAPI_E_NETWORK_ERROR               : szErr = L"MAPI_E_NETWORK_ERROR";           break;
	case MAPI_E_DISK_ERROR                  : szErr = L"MAPI_E_DISK_ERROR";              break;
	case MAPI_E_TOO_COMPLEX                 : szErr = L"MAPI_E_TOO_COMPLEX";             break;
	case MAPI_E_BAD_COLUMN                  : szErr = L"MAPI_E_BAD_COLUMN";              break;
	case MAPI_E_EXTENDED_ERROR              : szErr = L"MAPI_E_EXTENDED_ERROR";          break;
	case MAPI_E_COMPUTED                    : szErr = L"MAPI_E_COMPUTED";                break;
	case MAPI_E_CORRUPT_DATA                : szErr = L"MAPI_E_CORRUPT_DATA";            break;
	case MAPI_E_UNCONFIGURED                : szErr = L"MAPI_E_UNCONFIGURED";            break;
	case MAPI_E_FAILONEPROVIDER             : szErr = L"MAPI_E_FAILONEPROVIDER";         break;
	case MAPI_E_END_OF_SESSION              : szErr = L"MAPI_E_END_OF_SESSION";          break;
	case MAPI_E_UNKNOWN_ENTRYID             : szErr = L"MAPI_E_UNKNOWN_ENTRYID";         break;
	case MAPI_E_MISSING_REQUIRED_COLUMN     : szErr = L"MAPI_E_MISSING_REQUIRED_COLUMN"; break;
	case MAPI_W_NO_SERVICE                  : szErr = L"MAPI_W_NO_SERVICE";              break;
	case MAPI_E_BAD_VALUE                   : szErr = L"MAPI_E_BAD_VALUE";               break;
	case MAPI_E_INVALID_TYPE                : szErr = L"MAPI_E_INVALID_TYPE";            break;
	case MAPI_E_TYPE_NO_SUPPORT             : szErr = L"MAPI_E_TYPE_NO_SUPPORT";         break;
	case MAPI_E_UNEXPECTED_TYPE             : szErr = L"MAPI_E_UNEXPECTED_TYPE";         break;
	case MAPI_E_TOO_BIG                     : szErr = L"MAPI_E_TOO_BIG";                 break;
	case MAPI_E_DECLINE_COPY                : szErr = L"MAPI_E_DECLINE_COPY";            break;
	case MAPI_E_UNEXPECTED_ID               : szErr = L"MAPI_E_UNEXPECTED_ID";           break;
	case MAPI_W_ERRORS_RETURNED             : szErr = L"MAPI_W_ERRORS_RETURNED";         break;
	case MAPI_E_UNABLE_TO_COMPLETE          : szErr = L"MAPI_E_UNABLE_TO_COMPLETE";      break;
	case MAPI_E_TIMEOUT                     : szErr = L"MAPI_E_TIMEOUT";                 break;
	case MAPI_E_TABLE_EMPTY                 : szErr = L"MAPI_E_TABLE_EMPTY";             break;
	case MAPI_E_TABLE_TOO_BIG               : szErr = L"MAPI_E_TABLE_TOO_BIG";           break;
	case MAPI_E_INVALID_BOOKMARK            : szErr = L"MAPI_E_INVALID_BOOKMARK";        break;
	case MAPI_W_POSITION_CHANGED            : szErr = L"MAPI_W_POSITION_CHANGED";        break;
	case MAPI_W_APPROX_COUNT                : szErr = L"MAPI_W_APPROX_COUNT";            break;
	case MAPI_E_WAIT                        : szErr = L"MAPI_E_WAIT";                    break;
	case MAPI_E_CANCEL                      : szErr = L"MAPI_E_CANCEL";                  break;
	case MAPI_E_NOT_ME                      : szErr = L"MAPI_E_NOT_ME";                  break;
	case MAPI_W_CANCEL_MESSAGE              : szErr = L"MAPI_W_CANCEL_MESSAGE";          break;
	case MAPI_E_CORRUPT_STORE               : szErr = L"MAPI_E_CORRUPT_STORE";           break;
	case MAPI_E_NOT_IN_QUEUE                : szErr = L"MAPI_E_NOT_IN_QUEUE";            break;
	case MAPI_E_NO_SUPPRESS                 : szErr = L"MAPI_E_NO_SUPPRESS";             break;
	case MAPI_E_COLLISION                   : szErr = L"MAPI_E_COLLISION";               break;
	case MAPI_E_NOT_INITIALIZED             : szErr = L"MAPI_E_NOT_INITIALIZED";         break;
	case MAPI_E_NON_STANDARD                : szErr = L"MAPI_E_NON_STANDARD";            break;
	case MAPI_E_NO_RECIPIENTS               : szErr = L"MAPI_E_NO_RECIPIENTS";           break;
	case MAPI_E_SUBMITTED                   : szErr = L"MAPI_E_SUBMITTED";               break;
	case MAPI_E_HAS_FOLDERS                 : szErr = L"MAPI_E_HAS_FOLDERS";             break;
	case MAPI_E_HAS_MESSAGES                : szErr = L"MAPI_E_HAS_MESSAGES";            break;
	case MAPI_E_FOLDER_CYCLE                : szErr = L"MAPI_E_FOLDER_CYCLE";            break;
	case MAPI_W_PARTIAL_COMPLETION          : szErr = L"MAPI_W_PARTIAL_COMPLETION";      break;
	case MAPI_E_AMBIGUOUS_RECIP             : szErr = L"MAPI_E_AMBIGUOUS_RECIP";         break;

#ifndef MAPI_E_UNKNOWN_CPID
#define MAPI_E_UNKNOWN_CPID             MAKE_MAPI_E( 0x11E )
#define MAPI_E_UNKNOWN_LCID             MAKE_MAPI_E( 0x11F )
#endif

	case MAPI_E_UNKNOWN_CPID                : szErr = L"MAPI_E_UNKNOWN_CPID";            break;
	case MAPI_E_UNKNOWN_LCID                : szErr = L"MAPI_E_UNKNOWN_LCID";            break;

	case STG_E_INVALIDFUNCTION              : szErr = L"STG_E_INVALIDFUNCTION";          break;
	case STG_E_FILENOTFOUND                 : szErr = L"STG_E_FILENOTFOUND";             break;
	case STG_E_PATHNOTFOUND                 : szErr = L"STG_E_PATHNOTFOUND";             break;
	case STG_E_TOOMANYOPENFILES             : szErr = L"STG_E_TOOMANYOPENFILES";         break;
	case STG_E_ACCESSDENIED                 : szErr = L"STG_E_ACCESSDENIED";             break;
	case STG_E_INVALIDHANDLE                : szErr = L"STG_E_INVALIDHANDLE";            break;
	case STG_E_INSUFFICIENTMEMORY           : szErr = L"STG_E_INSUFFICIENTMEMORY";       break;
	case STG_E_INVALIDPOINTER               : szErr = L"STG_E_INVALIDPOINTER";           break;
	case STG_E_NOMOREFILES                  : szErr = L"STG_E_NOMOREFILES";              break;
	case STG_E_DISKISWRITEPROTECTED         : szErr = L"STG_E_DISKISWRITEPROTECTED";     break;
	case STG_E_SEEKERROR                    : szErr = L"STG_E_SEEKERROR";                break;
	case STG_E_WRITEFAULT                   : szErr = L"STG_E_WRITEFAULT";               break;
	case STG_E_READFAULT                    : szErr = L"STG_E_READFAULT";                break;
	case STG_E_SHAREVIOLATION               : szErr = L"STG_E_SHAREVIOLATION";           break;
	case STG_E_LOCKVIOLATION                : szErr = L"STG_E_LOCKVIOLATION";            break;
	case STG_E_FILEALREADYEXISTS            : szErr = L"STG_E_FILEALREADYEXISTS";        break;
	case STG_E_INVALIDPARAMETER             : szErr = L"STG_E_INVALIDPARAMETER";         break;
	case STG_E_MEDIUMFULL                   : szErr = L"STG_E_MEDIUMFULL";               break;
	case STG_E_ABNORMALAPIEXIT              : szErr = L"STG_E_ABNORMALAPIEXIT";          break;
	case STG_E_INVALIDHEADER                : szErr = L"STG_E_INVALIDHEADER";            break;
	case STG_E_INVALIDNAME                  : szErr = L"STG_E_INVALIDNAME";              break;
	case STG_E_UNKNOWN                      : szErr = L"STG_E_UNKNOWN";                  break;
	case STG_E_UNIMPLEMENTEDFUNCTION        : szErr = L"STG_E_UNIMPLEMENTEDFUNCTION";    break;
	case STG_E_INVALIDFLAG                  : szErr = L"STG_E_INVALIDFLAG";              break;
	case STG_E_INUSE                        : szErr = L"STG_E_INUSE";                    break;
	case STG_E_NOTCURRENT                   : szErr = L"STG_E_NOTCURRENT";               break;
	case STG_E_REVERTED                     : szErr = L"STG_E_REVERTED";                 break;
	case STG_E_CANTSAVE                     : szErr = L"STG_E_CANTSAVE";                 break;
	case STG_E_OLDFORMAT                    : szErr = L"STG_E_OLDFORMAT";                break;
	case STG_E_OLDDLL                       : szErr = L"STG_E_OLDDLL";                   break;
	case STG_E_SHAREREQUIRED                : szErr = L"STG_E_SHAREREQUIRED";            break;
	case STG_E_NOTFILEBASEDSTORAGE          : szErr = L"STG_E_NOTFILEBASEDSTORAGE";      break;
	case STG_S_CONVERTED                    : szErr = L"STG_S_CONVERTED";                break;

	case HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) :         szErr = L"WIN32 - ERROR_FILE_NOT_FOUND";         break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_DRIVE) :          szErr = L"WIN32 - ERROR_INVALID_DRIVE";          break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) :         szErr = L"WIN32 - ERROR_INVALID_HANDLE";         break;
	case HRESULT_FROM_WIN32(ERROR_SEEK) :                   szErr = L"WIN32 - ERROR_SEEK";                   break;
	case HRESULT_FROM_WIN32(ERROR_SECTOR_NOT_FOUND) :       szErr = L"WIN32 - ERROR_SECTOR_NOT_FOUND";       break;
	case HRESULT_FROM_WIN32(ERROR_WRITE_FAULT) :            szErr = L"WIN32 - ERROR_WRITE_FAULT";            break;
	case HRESULT_FROM_WIN32(ERROR_READ_FAULT) :             szErr = L"WIN32 - ERROR_READ_FAULT";             break;
	case HRESULT_FROM_WIN32(ERROR_SHARING_VIOLATION) :      szErr = L"WIN32 - ERROR_SHARING_VIOLATION";      break;
	case HRESULT_FROM_WIN32(ERROR_LOCK_VIOLATION) :         szErr = L"WIN32 - ERROR_LOCK_VIOLATION";         break;
	case HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED) :          szErr = L"WIN32 - ERROR_NOT_SUPPORTED";          break;
	case HRESULT_FROM_WIN32(ERROR_NO_SUCH_USER) :           szErr = L"WIN32 - ERROR_NO_SUCH_USER";           break;
	case HRESULT_FROM_WIN32(ERROR_NO_SUCH_GROUP) :          szErr = L"WIN32 - ERROR_NO_SUCH_GROUP";          break;
	case HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD) :         szErr = L"WIN32 - ERROR_WRONG_PASSWORD";         break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_PASSWORD) :       szErr = L"WIN32 - ERROR_INVALID_PASSWORD";       break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_FLAGS) :          szErr = L"WIN32 - ERROR_INVALID_FLAGS";          break;
	case HRESULT_FROM_WIN32(ERROR_BAD_USERNAME) :           szErr = L"WIN32 - ERROR_BAD_USERNAME";           break;
	case HRESULT_FROM_WIN32(ERROR_BROKEN_PIPE) :            szErr = L"WIN32 - ERROR_BROKEN_PIPE";            break;
	case HRESULT_FROM_WIN32(ERROR_PIPE_BUSY) :              szErr = L"WIN32 - ERROR_PIPE_BUSY";              break;
	case HRESULT_FROM_WIN32(ERROR_PIPE_NOT_CONNECTED):      szErr = L"WIN32 - ERROR_PIPE_NOT_CONNECTED";     break;
	case HRESULT_FROM_WIN32(ERROR_PIPE_CONNECTED):          szErr = L"WIN32 - ERROR_PIPE_CONNECTED";         break;
	case HRESULT_FROM_WIN32(ERROR_STATIC_INIT) :            szErr = L"WIN32 - ERROR_STATIC_INIT";            break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_FUNCTION) :       szErr = L"WIN32 - ERROR_INVALID_FUNCTION";       break;
	case HRESULT_FROM_WIN32(ERROR_EXCEPTION_IN_SERVICE):    szErr = L"WIN32 - ERROR_EXCEPTION_IN_SERVICE";   break;
	case HRESULT_FROM_WIN32(ERROR_CANCELLED):               szErr = L"WIN32 - ERROR_CANCELLED";              break;
	case HRESULT_FROM_WIN32(ERROR_PARTIAL_COPY):            szErr = L"WIN32 - ERROR_PARTIAL_COPY";           break;
	case HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER):     szErr = L"WIN32 - ERROR_INSUFFICIENT_BUFFER";    break;
	case HRESULT_FROM_WIN32(ERROR_NO_UNICODE_TRANSLATION):  szErr = L"WIN32 - ERROR_NO_UNICODE_TRANSLATION"; break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_ACCOUNT_NAME):    szErr = L"WIN32 - ERROR_INVALID_ACCOUNT_NAME";   break;
	case HRESULT_FROM_WIN32(ERROR_PRIVILEGE_NOT_HELD):      szErr = L"WIN32 - ERROR_INVALID_ACCOUNT_NAME";   break;
	case HRESULT_FROM_WIN32(ERROR_BAD_NET_NAME):            szErr = L"WIN32 - ERROR_BAD_NET_NAME";           break;
	case HRESULT_FROM_WIN32(ERROR_SERVICE_NO_THREAD):       szErr = L"WIN32 - ERROR_SERVICE_NO_THREAD";      break;
	case HRESULT_FROM_WIN32(ERROR_SHUTDOWN_IN_PROGRESS):    szErr = L"WIN32 - ERROR_SHUTDOWN_IN_PROGRESS";   break;
	case HRESULT_FROM_WIN32(ERROR_CONNECTION_INVALID):      szErr = L"WIN32 - ERROR_CONNECTION_INVALID";     break;
	case HRESULT_FROM_WIN32(ERROR_HANDLE_EOF):              szErr = L"WIN32 - ERROR_HANDLE_EOF";             break;
	case HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS):          szErr = L"WIN32 - ERROR_ALREADY_EXISTS";         break;
	case HRESULT_FROM_WIN32(ERROR_HOST_UNREACHABLE):        szErr = L"WIN32 - ERROR_HOST_UNREACHABLE";       break;
	case HRESULT_FROM_WIN32(ERROR_FILE_EXISTS):             szErr = L"WIN32 - ERROR_FILE_EXISTS";            break;
	case HRESULT_FROM_WIN32(ERROR_IO_PENDING):              szErr = L"WIN32 - ERROR_IO_PENDING";             break;
	case HRESULT_FROM_WIN32(ERROR_ILL_FORMED_PASSWORD):     szErr = L"WIN32 - ERROR_ILL_FORMED_PASSWORD";    break;
	case HRESULT_FROM_WIN32(ERROR_PASSWORD_RESTRICTION):    szErr = L"WIN32 - ERROR_PASSWORD_RESTRICTION";   break;
	case HRESULT_FROM_WIN32(ERROR_LOGON_FAILURE):           szErr = L"WIN32 - ERROR_LOGON_FAILURE";          break;
	case HRESULT_FROM_WIN32(ERROR_ACCOUNT_RESTRICTION):     szErr = L"WIN32 - ERROR_ACCOUNT_RESTRICTION";    break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_LOGON_HOURS):     szErr = L"WIN32 - ERROR_INVALID_LOGON_HOURS";    break;
	case HRESULT_FROM_WIN32(ERROR_INVALID_WORKSTATION):     szErr = L"WIN32 - ERROR_INVALID_WORKSTATION";    break;
	case HRESULT_FROM_WIN32(ERROR_PASSWORD_EXPIRED):        szErr = L"WIN32 - ERROR_PASSWORD_EXPIRED";       break;
	case HRESULT_FROM_WIN32(ERROR_ACCOUNT_DISABLED):        szErr = L"WIN32 - ERROR_ACCOUNT_DISABLED";       break;
	case HRESULT_FROM_WIN32(ERROR_NONE_MAPPED):             szErr = L"WIN32 - ERROR_NONE_MAPPED";            break;
	case HRESULT_FROM_WIN32(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) : szErr = L"WIN32 - ERROR_FAILED_SERVICE_CONTROLLER_CONNECT"; break;

	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_CALL_FAILED):              szErr = L"RPC Error - RPC_S_CALL_FAILED";            break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_CALL_FAILED_DNE):          szErr = L"RPC Error - RPC_S_CALL_FAILED_DNE";        break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_PROTOCOL_ERROR):           szErr = L"RPC Error - RPC_S_PROTOCOL_ERROR";         break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_UNSUPPORTED_TRANS_SYN):    szErr = L"RPC Error - RPC_S_UNSUPPORTED_TRANS_SYN";  break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_UNSUPPORTED_TYPE):         szErr = L"RPC Error - RPC_S_UNSUPPORTED_TYPE";       break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_TAG):              szErr = L"RPC Error - RPC_S_INVALID_TAG";            break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_BOUND):            szErr = L"RPC Error - RPC_S_INVALID_BOUND";          break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NO_ENTRY_NAME):            szErr = L"RPC Error - RPC_S_NO_ENTRY_NAME";          break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_NAME_SYNTAX):      szErr = L"RPC Error - RPC_S_INVALID_NAME_SYNTAX";    break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_UNSUPPORTED_NAME_SYNTAX):  szErr = L"RPC Error - RPC_S_UNSUPPORTED_NAME_SYNTAX";break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_DUPLICATE_ENDPOINT):       szErr = L"RPC Error - RPC_S_DUPLICATE_ENDPOINT";     break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_STRING_BINDING):   szErr = L"RPC Error - RPC_S_INVALID_STRING_BINDING"; break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_WRONG_KIND_OF_BINDING):    szErr = L"RPC Error - RPC_S_WRONG_KIND_OF_BINDING";  break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_BINDING):          szErr = L"RPC Error - RPC_S_INVALID_BINDING";        break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_PROTSEQ_NOT_SUPPORTED):    szErr = L"RPC Error - RPC_S_PROTSEQ_NOT_SUPPORTED";  break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_RPC_PROTSEQ):      szErr = L"RPC Error - RPC_S_INVALID_RPC_PROTSEQ";    break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_STRING_UUID):      szErr = L"RPC Error - RPC_S_INVALID_STRING_UUID";    break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_ENDPOINT_FORMAT):  szErr = L"RPC Error - RPC_S_INVALID_ENDPOINT_FORMAT";break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_NET_ADDR):         szErr = L"RPC Error - RPC_S_NO_ENDPOINT_FOUND";      break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NO_ENDPOINT_FOUND):        szErr = L"RPC Error - RPC_S_DUPLICATE_ENDPOINT";     break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_INVALID_TIMEOUT):          szErr = L"RPC Error - RPC_S_INVALID_TIMEOUT";        break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_OBJECT_NOT_FOUND):         szErr = L"RPC Error - RPC_S_OBJECT_NOT_FOUND";       break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_ALREADY_REGISTERED):       szErr = L"RPC Error - RPC_S_ALREADY_REGISTERED";     break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_TYPE_ALREADY_REGISTERED):  szErr = L"RPC Error - RPC_S_TYPE_ALREADY_REGISTERED";break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_ALREADY_LISTENING):        szErr = L"RPC Error - RPC_S_ALREADY_LISTENING";      break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NO_PROTSEQS_REGISTERED):   szErr = L"RPC Error - RPC_S_NO_PROTSEQS_REGISTERED"; break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NOT_LISTENING):            szErr = L"RPC Error - RPC_S_NOT_LISTENING";          break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_UNKNOWN_MGR_TYPE):         szErr = L"RPC Error - RPC_S_UNKNOWN_MGR_TYPE";       break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_UNKNOWN_IF):               szErr = L"RPC Error - RPC_S_UNKNOWN_IF";             break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NO_BINDINGS):              szErr = L"RPC Error - RPC_S_NO_BINDINGS";            break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_NO_PROTSEQS):              szErr = L"RPC Error - RPC_S_NO_PROTSEQS";            break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_CANT_CREATE_ENDPOINT):     szErr = L"RPC Error - RPC_S_CANT_CREATE_ENDPOINT";   break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_OUT_OF_RESOURCES):         szErr = L"RPC Error - RPC_S_OUT_OF_RESOURCES";       break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_SERVER_UNAVAILABLE):       szErr = L"RPC Error - RPC_S_SERVER_UNAVAILABLE";     break;
	case MAKE_HRESULT(1, FACILITY_RPC, RPC_S_SERVER_TOO_BUSY):          szErr = L"RPC Error - RPC_S_SERVER_TOO_BUSY";        break;

	default : szErr = L"UNKNOWN"; break;
	}   

	return szErr;
}

BOOL otlkcon_debug::GetPropValue(
	LPSPropValue lpPropValue,
	wchar_t* lpszBuffer,
	size_t cchBufferLenght)
{
	union _PV * pVal = &lpPropValue->Value;
	wchar_t * lpszEndMessage = lpszBuffer; // in order to have empty string to write
	size_t cchRemainingMessage = cchBufferLenght;

	WCHAR wzVal[512] = {0};

	ULONG cbSize = 0;
	ULONG i = 0;
	char szVal [512] = {0};
	LPOLESTR lpszOle = NULL;
	TCHAR gu[256] = {0};
	
	switch (PROP_TYPE(lpPropValue->ulPropTag))
	{
	case PT_STRING8 :
		if (NULL != pVal->lpszA)
		{
			//obtaining just a peace of data
			StringCchCopyA(szVal, cch(szVal), pVal->lpszA);
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"'%S'",
				szVal);
		}
		else
		{
			StringCchCopyExW(lpszEndMessage, cchRemainingMessage, L"NULL",
				&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		}
		break;
	case PT_UNICODE :
		if(NULL != pVal->lpszW)
		{
			StringCchCopyW(wzVal, cch(wzVal), pVal->lpszW);
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"'%s'",
				wzVal);
		}
		else
		{
			StringCchCopyExW(lpszEndMessage, cchRemainingMessage, L"NULL",
				&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		}
		break;
	case PT_UNSPECIFIED :  
	case PT_NULL : 
		StringCchCopyExW(lpszEndMessage, cchRemainingMessage, L"?",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_SHORT:
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#x %d",
			pVal->i, pVal->i);
		break;
	case PT_LONG:
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#lx %ld",
			pVal->l, pVal->l);
			break;
		break;
	case PT_FLOAT :              
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#g",
			pVal->flt);
		break;
	case PT_DOUBLE :
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#g",
			pVal->dbl);
		break;
	case PT_CURRENCY :
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%I64d",
			pVal->cur.int64);
		break;
	case PT_APPTIME :
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#g",
			pVal->at);
		break;
	case PT_ERROR:
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#lx %s",
			pVal->err, GetErrorString(pVal->err));
		break;
	case PT_BOOLEAN :            
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%s",
			pVal->b?L"true":L"false");
		break;
	case PT_OBJECT :             
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#lx",
			pVal->x);
		break;
	case PT_I8 :                     
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%#I64x %I64d",
			pVal->li.QuadPart, pVal->li.QuadPart);
		break;
	case PT_SYSTIME :
		{
			wchar_t szTime[MAX_PATH+1] = {0};
			FileTimeToSTR(&pVal->ft, szTime, cch(szTime));
			LONGLONG *val = (LONGLONG*)&pVal->ft;

			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"%#I64x %s",
				*val, szTime);
			break;
		}
		break;
	case PT_CLSID :
		lpszOle = (LPOLESTR) gu;
		StringFromGUID2(*(pVal->lpguid), lpszOle, cch(gu));

		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"%s",
			lpszOle);
		break;
	case PT_BINARY :
		if (pVal->bin.cb > 0)
		{
			if(pVal->bin.cb > 0 && pVal->bin.lpb != NULL)
			{
				int kMin = min(256, pVal->bin.cb);

				StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
					L"{ cb:%d pb:",
					pVal->bin.cb);
				for (int i = 0; i < kMin; i++)
				{
					StringCchPrintfExW(lpszEndMessage, cchRemainingMessage,&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
						L" %02x",
						*((BYTE*)(pVal->bin.lpb + i)));
				}
				if (pVal->bin.cb > 256)
				{
					StringCchCatExW(lpszEndMessage, cchRemainingMessage, L" ... }",
						&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
				}
				else
				{
					StringCchCatExW(lpszEndMessage, cchRemainingMessage, L" }",
						&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
				}
			}
			else
			{
				StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
					L"{ cb:%d pb:%#x}",
					pVal->bin.cb, pVal->bin.lpb);
			}
			break;
		}
		else
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"{ NULL }");
			break;
		}
		break;

		// Multi-value properties
	case PT_MV_SHORT :
		cbSize = pVal->MVi.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d {\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %#x %d\r\n",
				i, pVal->MVi.lpi[i], pVal->MVi.lpi[i]);

		}
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_MV_LONG :
		cbSize = pVal->MVl.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %#lx %ld\r\n",
				i, pVal->MVl.lpl[i], pVal->MVl.lpl[i]);
		}
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_MV_FLOAT :
		cbSize = pVal->MVflt.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %#g\r\n",
				i, pVal->MVflt.lpflt[i]);
		}
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_MV_APPTIME :
	case PT_MV_DOUBLE :
		cbSize = pVal->MVdbl.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %#g\r\n",
				i, pVal->MVdbl.lpdbl[i]);
		} // for
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_MV_CURRENCY :
		cbSize = pVal->MVcur.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %I64d\r\n",
				i, pVal->MVcur.lpcur[i]);
		} // for
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
	case PT_MV_SYSTIME:
		{
			cbSize = pVal->MVft.cValues;
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"cValues = %d{\r\n",
				cbSize);
			wchar_t szTime[MAX_PATH+1] = {0};
			for (i = 0; i < cbSize; i++)
			{
				FileTimeToSTR(&pVal->MVft.lpft[i], szTime, cch(szTime));
				StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
					L"\t#%02d) %#I64x %s\r\n",
					i, pVal->MVft.lpft[i], szTime);
			}
			StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
				&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		} // for
		break;
	case PT_MV_I8 :
		cbSize = pVal->MVli.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"\t#%02d) %#I64x %I64d\r\n",
				i, pVal->MVli.lpli[i], pVal->MVli.lpli[i]);
		} // for
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;
//		case PT_MV_CLSID :
//			cbSize *= cch(GUID);
//			break;
	case PT_MV_STRING8 :
		{
			cbSize = pVal->MVszA.cValues;
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"cValues = %d{\r\n",
				cbSize);
			for (ULONG i=0; i<pVal->MVszA.cValues; i++)
			{
				if(pVal->MVszA.lppszA[i])
				{
					StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
						L"\t#%02d) '%S'\r\n",
						i, pVal->MVszA.lppszA[i]);
				}
				else
				{
					StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
						L"\t#%02d) NULL\r\n",
						i);
				}
			} // for
			StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
				&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		}
		break;
	case PT_MV_UNICODE :
		{
			cbSize = pVal->MVszW.cValues;
			StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
				L"cValues = %d{\r\n",
				cbSize);
			for (ULONG i=0; i<pVal->MVszW.cValues; i++)
			{
				if(pVal->MVszW.lppszW[i])
				{
					StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
						L"\t#%02d) '%s'\r\n",
						i, pVal->MVszW.lppszW[i]);
				}
				else
				{
					StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
						L"\t#%02d) NULL\r\n",
						i);
				}
			}
			StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
				&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		}
		break;
	case PT_MV_BINARY:
		cbSize = pVal->MVbin.cValues;
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"cValues = %d{\r\n",
			cbSize);
		for (i = 0; i < cbSize; i++)
		{
			int L = sizeof(BYTE);
			SBinary ppBin = pVal->MVbin.lpbin[i];
			if (ppBin.cb > 0 && ppBin.lpb != NULL)
			{
				StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
					L"\t#%02d) { cb:%d pb:",
					i, ppBin.cb);
				int kMin = min(256, ppBin.cb);
				for (int k = 0; k < kMin; k++)
				{
					try
					{
						StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
							L" %02x",
							*((BYTE*) (ppBin.lpb + k * L)));
					}
					catch (...)
					{
						StringCchCatExW(lpszEndMessage, cchRemainingMessage, L" ??",
							&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
						break;
					}
				}
				if (ppBin.cb > 256)
				{
					StringCchCatExW(lpszEndMessage, cchRemainingMessage, L" ... }\r\n",
						&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
				}
				else
				{
					StringCchCatExW(lpszEndMessage, cchRemainingMessage, L" }\r\n",
						&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
				}
			}
			else
			{
				StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
					L"\t#%02d) { cb:%d pb:%#x}\r\n",
					i, ppBin.cb, ppBin.lpb);
			}
		} // for
		StringCchCatExW(lpszEndMessage, cchRemainingMessage, L"}",
			&lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS);
		break;

	default :
		StringCchPrintfExW(lpszEndMessage, cchRemainingMessage, &lpszEndMessage, &cchRemainingMessage, STRSAFE_IGNORE_NULLS,
			L"???");
		break;
	}

	return TRUE;
}

void otlkcon_debug::TracePropValue(
	ULONG ulTraceFlags,
	LPSPropValue lpPropValue,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;

	wchar_t szTagName[4096] = {0};
	wchar_t szValue[4096] = {0};

	if(GetTagName(lpPropValue->ulPropTag, szTagName, cch(szTagName)))
	{
		if(GetPropValue(lpPropValue, szValue, cch(szValue)))
		{
			OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: %s = %s\n", lpszMessage, szTagName, szValue);
		} // if
	} // if
}

void otlkcon_debug::TracePropValueArray(
	ULONG ulTraceFlags,
	LPSPropValue lpPropValues,
	ULONG cValues,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;

	wchar_t szTagName[4096] = {0};
	wchar_t szValue[4096] = {0};

	OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: cValues = %d\n", lpszMessage, cValues);
	for(ULONG iProp = 0; iProp < cValues; iProp++)
	{
		if(GetTagName(lpPropValues[iProp].ulPropTag, szTagName, cch(szTagName)))
		{
			if(GetPropValue(&lpPropValues[iProp], szValue, cch(szValue)))
			{
				OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"\t%s = %s\n", szTagName, szValue);
			} // if
		} // if
	} // for
}

void otlkcon_debug::TraceSRow(
	ULONG ulTraceFlags,
	LPSRow lpRow,
	wchar_t* lpszMessage)
{
	TracePropValueArray(ulTraceFlags, lpRow->lpProps, lpRow->cValues, lpszMessage);
}

void otlkcon_debug::TraceSRowSet(
	ULONG ulTraceFlags,
	LPSRowSet lpRowSet,
	wchar_t* lpszMessage)
{
	if(!m_bInitialized) return;
	if(!CanTrace(ulTraceFlags)) return;

	OTLKCON_LOG_PRINTF(OTLKCON_LOG_LEVEL_INFO, ulTraceFlags, L"%s: cRows = %d\n", lpszMessage, lpRowSet->cRows);
	wchar_t szRowMessage[MAX_PATH+1] = {0};

	for(ULONG iRow = 0; iRow < lpRowSet->cRows; iRow++)
	{
		StringCchPrintfW(szRowMessage, cch(szRowMessage),
			L"%d row", iRow);
		TraceSRow(ulTraceFlags, &lpRowSet->aRow[iRow], szRowMessage);
	} // for
}